package com.note.app.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.houbb.sensitive.word.core.SensitiveWordHelper;
import com.note.app.dto.CollectionCreateDTO;
import com.note.app.dto.CollectionDTO;
import com.note.app.dto.CollectionQueryDTO;
import com.note.app.dto.CollectionUpdateDTO;
import com.note.app.mapper.CollectionMapper;
import com.note.app.service.CollectionService;
import com.note.common.domain.DocCollection;
import com.note.common.vo.ResponseVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 集合服务实现类
 */
@Slf4j
@Service
public class CollectionServiceImpl implements CollectionService {

    @Autowired
    private CollectionMapper collectionMapper;
    
    @Value("${sensitive.word.threshold:10}")
    private int sensitiveWordThreshold;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseVo<CollectionDTO> createCollection(Long userId, CollectionCreateDTO createDTO) {
        // 1. 检查父级集合是否存在（如果指定了父级集合）
        if (createDTO.getParentId() != null && createDTO.getParentId() > 0) {
            DocCollection parent = collectionMapper.selectById(createDTO.getParentId());
            if (parent == null || parent.getDeleted() == 1) {
                return ResponseVo.paramError("父级集合不存在");
            }
            
            // 检查父级集合是否属于当前用户
            if (!parent.getUserId().equals(userId)) {
                return ResponseVo.forbidden();
            }
        }
        
        // 1.1 敏感词过滤
        String name = createDTO.getName();
        String description = createDTO.getDescription();
        
        // 检查名称敏感词
        if (name != null && !name.isEmpty()) {
            List<String> nameSensitiveWords = SensitiveWordHelper.findAll(name);
            
            if (nameSensitiveWords.size() > sensitiveWordThreshold) {
                return ResponseVo.paramError("集合名称包含过多违规内容，请修改后重试，违规词数量：" + nameSensitiveWords.size());
            }
            
            // 替换敏感词
            if (!nameSensitiveWords.isEmpty()) {
                createDTO.setName(SensitiveWordHelper.replace(name));
            }
        }
        
        // 检查描述敏感词
        if (description != null && !description.isEmpty()) {
            List<String> descSensitiveWords = SensitiveWordHelper.findAll(description);
            
            if (descSensitiveWords.size() > sensitiveWordThreshold) {
                return ResponseVo.paramError("集合描述包含过多违规内容，请修改后重试，违规词数量：" + descSensitiveWords.size());
            }
            
            // 替换敏感词
            if (!descSensitiveWords.isEmpty()) {
                createDTO.setDescription(SensitiveWordHelper.replace(description));
            }
        }
        
        // 2. 创建集合对象
        DocCollection collection = new DocCollection();
        collection.setUserId(userId);
        collection.setParentId(createDTO.getParentId());
        collection.setName(createDTO.getName());
        collection.setDescription(createDTO.getDescription());
        collection.setIcon(createDTO.getIcon());
        collection.setEmoji(createDTO.getEmoji());
        collection.setCreatedAt(LocalDateTime.now());
        collection.setUpdatedAt(LocalDateTime.now());
        
        // 3. 保存到数据库
        collectionMapper.insert(collection);
        log.info("创建集合成功: userId={}, collectionId={}, name={}, emoji={}", 
                userId, collection.getId(), collection.getName(), collection.getEmoji());
        
        // 4. 返回创建结果
        CollectionDTO dto = convertToDto(collection);
        return ResponseVo.success("创建成功", dto);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseVo<CollectionDTO> updateCollection(Long userId, CollectionUpdateDTO updateDTO) {
        // 1. 检查集合是否存在且归当前用户所有
        DocCollection collection = collectionMapper.selectById(updateDTO.getId());
        if (collection == null || collection.getDeleted() == 1) {
            return ResponseVo.notFound("集合不存在");
        }
        
        if (!collection.getUserId().equals(userId)) {
            return ResponseVo.forbidden();
        }
        
        // 2. 检查父级集合是否存在（如果指定了父级集合）
        if (updateDTO.getParentId() != null) {
            // 避免自己作为自己的父级
            if (updateDTO.getId().equals(updateDTO.getParentId())) {
                return ResponseVo.paramError("不能将集合自身设为父级");
            }
            
            // 检查是否形成循环引用
            if (isCircularReference(updateDTO.getId(), updateDTO.getParentId())) {
                return ResponseVo.paramError("不能将子集合设为父级，会形成循环引用");
            }
            
            if (updateDTO.getParentId() > 0) {
                DocCollection parent = collectionMapper.selectById(updateDTO.getParentId());
                if (parent == null || parent.getDeleted() == 1) {
                    return ResponseVo.paramError("父级集合不存在");
                }
                
                // 检查父级集合是否属于当前用户
                if (!parent.getUserId().equals(userId)) {
                    return ResponseVo.forbidden();
                }
            }
            
            collection.setParentId(updateDTO.getParentId());
        }
        
        // 2.1 敏感词过滤
        String name = updateDTO.getName();
        String description = updateDTO.getDescription();
        
        // 检查名称敏感词
        if (name != null && !name.isEmpty()) {
            List<String> nameSensitiveWords = SensitiveWordHelper.findAll(name);
            
            if (nameSensitiveWords.size() > sensitiveWordThreshold) {
                return ResponseVo.paramError("集合名称包含过多违规内容，请修改后重试，违规词数量：" + nameSensitiveWords.size());
            }
            
            // 替换敏感词
            if (!nameSensitiveWords.isEmpty()) {
                updateDTO.setName(SensitiveWordHelper.replace(name));
            }
        }
        
        // 检查描述敏感词
        if (description != null && !description.isEmpty()) {
            List<String> descSensitiveWords = SensitiveWordHelper.findAll(description);
            
            if (descSensitiveWords.size() > sensitiveWordThreshold) {
                return ResponseVo.paramError("集合描述包含过多违规内容，请修改后重试，违规词数量：" + descSensitiveWords.size());
            }
            
            // 替换敏感词
            if (!descSensitiveWords.isEmpty()) {
                updateDTO.setDescription(SensitiveWordHelper.replace(description));
            }
        }
        
        // 3. 更新集合
        if (StringUtils.hasText(updateDTO.getName())) {
            collection.setName(updateDTO.getName());
        }
        
        collection.setDescription(updateDTO.getDescription());
        
        // 更新icon和emoji字段
        if (updateDTO.getIcon() != null) {
            collection.setIcon(updateDTO.getIcon());
        }
        
        if (updateDTO.getEmoji() != null) {
            collection.setEmoji(updateDTO.getEmoji());
        }
        
        collection.setUpdatedAt(LocalDateTime.now());
        
        // 4. 保存到数据库
        collectionMapper.updateById(collection);
        log.info("更新集合成功: userId={}, collectionId={}, emoji={}", 
                userId, collection.getId(), collection.getEmoji());
        
        // 5. 返回更新结果
        CollectionDTO dto = convertToDto(collection);
        return ResponseVo.success("更新成功", dto);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseVo<Void> deleteCollection(Long userId, Long collectionId) {
        // 1. 检查集合是否存在且归当前用户所有
        DocCollection collection = collectionMapper.selectById(collectionId);
        if (collection == null || collection.getDeleted() == 1) {
            return ResponseVo.notFound("集合不存在");
        }
        
        if (!collection.getUserId().equals(userId)) {
            return ResponseVo.forbidden();
        }
        
        // 2. 检查是否有子集合
        LambdaQueryWrapper<DocCollection> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DocCollection::getParentId, collectionId)
                   .eq(DocCollection::getDeleted, 0);
        
        Long childCount = collectionMapper.selectCount(queryWrapper);
        if (childCount > 0) {
            return ResponseVo.paramError("该集合下有子集合，无法删除");
        }
        
        // 3. 逻辑删除集合
        collection.setDeleted(1);
        collection.setUpdatedAt(LocalDateTime.now());
        collectionMapper.updateById(collection);
        
        log.info("删除集合成功: userId={}, collectionId={}", userId, collectionId);
        return ResponseVo.success("删除成功");
    }

    @Override
    public ResponseVo<CollectionDTO> getCollection(Long userId, Long collectionId) {
        // 1. 检查集合是否存在且归当前用户所有
        DocCollection collection = collectionMapper.selectById(collectionId);
        if (collection == null || collection.getDeleted() == 1) {
            return ResponseVo.notFound("集合不存在");
        }
        
        if (!collection.getUserId().equals(userId)) {
            return ResponseVo.forbidden();
        }
        
        // 2. 查询子集合
        List<DocCollection> children = collectionMapper.selectChildrenByParentId(userId, collectionId);
        
        // 3. 转换为DTO并设置子集合
        CollectionDTO dto = convertToDto(collection);
        dto.setChildren(convertToDtoList(children));
        
        return ResponseVo.success(dto);
    }

    @Override
    public ResponseVo<IPage<CollectionDTO>> pageCollections(Long userId, CollectionQueryDTO queryDTO) {
        // 1. 创建分页对象
        Page<DocCollection> page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize());
        
        // 2. 查询分页数据
        IPage<DocCollection> collectionPage = collectionMapper.selectPageByUserId(
                page, userId, queryDTO.getParentId());
        
        // 3. 转换为DTO
        IPage<CollectionDTO> dtoPage = collectionPage.convert(this::convertToDto);
        
        return ResponseVo.success(dtoPage);
    }

    @Override
    public ResponseVo<List<CollectionDTO>> getCollectionTree(Long userId) {
        // 1. 查询用户所有集合
        List<DocCollection> allCollections = collectionMapper.selectAllByUserId(userId);
        
        // 2. 构建集合树
        List<CollectionDTO> tree = buildCollectionTree(allCollections, null);
        
        return ResponseVo.success(tree);
    }
    
    /**
     * 构建集合树形结构
     * 
     * @param collections 集合列表
     * @param parentId 父级ID
     * @return 树形结构
     */
    private List<CollectionDTO> buildCollectionTree(List<DocCollection> collections, Long parentId) {
        // 根据父级ID筛选符合条件的节点
        List<DocCollection> nodes = collections.stream()
                .filter(c -> {
                    if (parentId == null) {
                        return c.getParentId() == null || c.getParentId() == 0;
                    } else {
                        return Objects.equals(c.getParentId(), parentId);
                    }
                })
                .collect(Collectors.toList());
        
        // 递归构建子节点
        return nodes.stream().map(node -> {
            CollectionDTO dto = convertToDto(node);
            dto.setChildren(buildCollectionTree(collections, node.getId()));
            return dto;
        }).collect(Collectors.toList());
    }
    
    /**
     * 检查是否形成循环引用
     * 
     * @param collectionId 当前集合ID
     * @param newParentId 新父级ID
     * @return 是否形成循环引用
     */
    private boolean isCircularReference(Long collectionId, Long newParentId) {
        // 空父级ID不会形成循环引用
        if (newParentId == null || newParentId == 0) {
            return false;
        }
        
        // 找出所有子集合
        Set<Long> childIds = new HashSet<>();
        collectChildIds(childIds, collectionId);
        
        // 如果子集合中包含新父级ID，则会形成循环引用
        return childIds.contains(newParentId);
    }
    
    /**
     * 收集所有子集合ID
     * 
     * @param childIds 子集合ID集合
     * @param parentId 父级ID
     */
    private void collectChildIds(Set<Long> childIds, Long parentId) {
        LambdaQueryWrapper<DocCollection> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DocCollection::getParentId, parentId)
                   .eq(DocCollection::getDeleted, 0);
        
        List<DocCollection> children = collectionMapper.selectList(queryWrapper);
        for (DocCollection child : children) {
            childIds.add(child.getId());
            collectChildIds(childIds, child.getId());
        }
    }
    
    /**
     * 将实体转换为DTO
     */
    private CollectionDTO convertToDto(DocCollection collection) {
        CollectionDTO dto = new CollectionDTO();
        BeanUtils.copyProperties(collection, dto);
        return dto;
    }
    
    /**
     * 将实体列表转换为DTO列表
     */
    private List<CollectionDTO> convertToDtoList(List<DocCollection> collections) {
        return collections.stream()
                .map(this::convertToDto)
                .collect(Collectors.toList());
    }
} 